import time
from http.client import responses

import requests
from bs4 import BeautifulSoup
import json


# --- 步骤1：模拟从线上API获取所有在售的商品ID ---
def get_all_active_product_ids(qunar_session):
    """
    【重要】这是一个模拟函数。
    在实际应用中，您需要替换这里的逻辑，通过真实的网络请求
    去获取当前所有有效的、在售的商品ID列表。
    """
    active_ids = set()
    url = "https://b2b.piao.qunar.com/product/list?sightId=1174758904"
    cookie = {
        "_s": qunar_session
    }
    response = requests.get(url=url, cookies=cookie)
    soup = BeautifulSoup(response.text, 'html.parser')
    # 2. 查找所有符合条件的td标签：<td data-tips="usage">
    #    我们使用 attrs 参数来指定属性
    target_tds = soup.find_all('td', attrs={'data-tips': 'usage'})

    # 3. 遍历找到的每一个td标签
    for td in target_tds:
        # 4. 获取这个td标签的父tr标签
        #    使用 .find_parent('tr') 来查找最近的<tr>父元素
        parent_tr = td.find_parent('tr')

        if parent_tr:
            # 5. 在父tr标签下，获取第一个td标签
            #    使用 .find('td') 只会返回第一个匹配项
            first_td = parent_tr.find('td')

            if first_td:
                # 6. 获取第一个td标签的内容
                #    .get_text(strip=True) 可以获取纯文本并去除首尾空白
                content = first_td.get_text(strip=True)
                active_ids.add(content)  # 添加到集合
    return active_ids


# --- 步骤2：加载本地配置 ---
def load_ticket_config(filepath="qunar_config.json"):
    """从JSON文件加载门票配置"""
    try:
        with open(filepath, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        print(f"错误: 配置文件 {filepath} 未找到。")
        return {}
    except json.JSONDecodeError:
        print(f"错误: 配置文件 {filepath} 格式不正确。")
        return {}


def get_price_for_id(session, product_id):
    """获取指定商品ID的价格日历

    参数:
        session: 认证会话的cookie值
        product_id: 商品ID

    返回:
        字典格式的价格日历 {日期: 价格}
    """
    # 生成当前毫秒级时间戳
    millisecond_timestamp = int(time.time() * 1000)

    # 构建请求URL
    url = f"https://b2b.piao.qunar.com/order/queryProductDate?method=queryProductDate&productId={product_id}&_={millisecond_timestamp}"

    # 设置Cookie
    cookies = {"_s": session}

    try:
        # 发送GET请求
        response = requests.get(url, cookies=cookies)
        response.raise_for_status()  # 检查HTTP错误

        # 解析JSON响应
        json_data = response.json()

        # 检查数据结构是否有效
        if "data" not in json_data or not isinstance(json_data["data"], list):
            print(f"警告: 商品 {product_id} 返回的价格数据格式异常")
            return {}

        # 初始化价格字典
        price_dict = {}

        # 遍历data列表中的每个日期项
        for date_data in json_data["data"]:
            # 确保date_data是字典类型
            if not isinstance(date_data, dict):
                continue

            # 提取日期和价格
            use_date = date_data.get("useDate")
            qunar_price = date_data.get("qunarPrice")

            # 确保数据有效
            if use_date and qunar_price is not None:
                price_dict[use_date] = qunar_price

        return price_dict

    except requests.exceptions.RequestException as e:
        print(f"请求失败: {e}")
        return {}
    except (ValueError, IndexError, TypeError) as e:
        print(f"解析响应失败: {e}")
        return {}

# --- 主程序逻辑 ---

if __name__ == "__main__":
    # 1. 加载本地配置
    local_config = load_ticket_config()
    if not local_config:
        exit()  # 如果配置加载失败，则退出程序

    # 提取本地配置中的所有ID到一个集合中，方便比对
    all_local_ids = set()
    for id_list in local_config.values():
        all_local_ids.update(id_list)

    qunar_session = input("请输入去哪儿session:")
    # 2. 从“API”获取当前所有有效的ID
    active_ids_from_api = get_all_active_product_ids(qunar_session)

    print("\n--- 开始同步与校验 ---")

    # 3. 对比差异
    # 使用集合的减法(-)找出新增ID
    new_ids = active_ids_from_api - all_local_ids
    # 使用集合的减法(-)找出丢失ID
    lost_ids = all_local_ids - active_ids_from_api
    # 使用集合的交集(&)找出需要处理的有效ID
    valid_ids = all_local_ids & active_ids_from_api

    # 4. 处理结果
    if new_ids:
        print(f"\n[!] 发现 {len(new_ids)} 个新增商品ID，请手动更新 config.json 文件进行分类：")
        for new_id in new_ids:
            print(f"  - {new_id}")

    if lost_ids:
        print(f"\n[*] 检测到 {len(lost_ids)} 个商品ID已在线上丢失/下架，本次将忽略它们：")
        for lost_id in lost_ids:
            print(f"  - {lost_id}")

    print("\n--- 同步校验完成 ---")

    # 5. 生成本次运行实际要使用的、过滤后的配置
    runtime_config = {}
    for ticket_type, id_list in local_config.items():
        # 只保留那些有效的ID
        active_id_list = [id_ for id_ in id_list if id_ in valid_ids]
        if active_id_list:  # 如果这个票种下还有有效的ID，才加入到运行时配置中
            runtime_config[ticket_type] = active_id_list

    print("\n[✓] 本次运行将使用的有效配置：")
    print(json.dumps(runtime_config, indent=2, ensure_ascii=False))

    # 6. 后续就可以使用这个 `runtime_config` 去安全地获取价格日历了
    while True:
        print("\n--- 开始查询价格 ---")
        # 用户选择票种
        target_ticket_type_number = input("请输入门票类型编号\n"
                                   "1:成人1日票\n"
                                   "2:儿童1日票\n"
                                   "3:长者1日票\n"
                                   "4:1大1小\n"
                                   "5:2大1小\n"
                                   "6:大学生票\n"
                                   "7:成人2日票\n"
                                   "8:儿童2日票\n"
                                   "9:长者2日票\n")
        target_ticket_type_dict = {
            "1": "成人1日票",
            "2": "儿童1日票",
            "3": "长者1日票",
            "4": "1大1小",
            "5": "2大1小",
            "6": "大学生票",
            "7": "成人2日票",
            "8": "儿童2日票",
            "9": "长者2日票"
        }
        target_ticket_type = target_ticket_type_dict.get(target_ticket_type_number)
        ids_to_query = runtime_config.get(target_ticket_type, [])

        if ids_to_query:
            print(f"需要为「{target_ticket_type}」查询以下ID的价格：{ids_to_query}")
            # 存储所有商品的价格日历
            all_price_calendars = {}

            # 为每个ID获取价格日历
            for product_id in ids_to_query:
                price_calendar = get_price_for_id(qunar_session, product_id)
                all_price_calendars[product_id] = price_calendar
                print(f"已获取商品 {product_id} 的价格日历，包含 {len(price_calendar)} 天的价格")

            # 用户选择日期
            selected_date = input("\n请输入您要查询的日期（格式：YYYY-MM-DD）：")

            # 收集该日期所有可用商品的价格
            prices_on_date = []

            for product_id, calendar in all_price_calendars.items():
                if selected_date in calendar:
                    price = calendar[selected_date]
                    prices_on_date.append((product_id, price))

            if not prices_on_date:
                print(f"\n⚠️ 在 {selected_date} 没有找到任何可用的商品")
            else:
                # 按价格排序（从低到高）
                prices_on_date.sort(key=lambda x: x[1])

                # 获取最便宜的前三个
                cheapest_three = prices_on_date[:3]

                print(f"\n在 {selected_date} 最便宜的前三个商品：")
                for rank, (product_id, price) in enumerate(cheapest_three, 1):
                    print(f"第{rank}名: 商品ID {product_id} - 价格 ¥{price}")

                # 如果需要，可以返回这些商品ID用于后续操作
                cheapest_ids = [item[0] for item in cheapest_three]
                print(f"\n最便宜的三个商品ID: {cheapest_ids}")
        else:
            print(f"「{target_ticket_type}」下没有有效的商品ID可供查询。")
